package cn.stylefeng.guns.modular.rest.track;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.stylefeng.guns.modular.basic.entity.BasicPrivatecar;
import cn.stylefeng.guns.modular.basic.service.BasicPrivatecarService;
import cn.stylefeng.guns.modular.rest.aop.UserAop;
import cn.stylefeng.guns.modular.transport.entity.MapDisptch;
import cn.stylefeng.guns.modular.transport.entity.MapDisptchMongo;
import cn.stylefeng.guns.modular.transport.entity.MapPoints;
import cn.stylefeng.guns.modular.transport.entity.Trace;
import cn.stylefeng.guns.modular.transport.model.params.MapDisptchParam;
import cn.stylefeng.guns.modular.transport.model.params.TraceParam;
import cn.stylefeng.guns.modular.transport.model.result.MapDisptchResult;
import cn.stylefeng.guns.modular.transport.model.result.MapServiceResult;
import cn.stylefeng.guns.modular.transport.service.MapDisptchService;
import cn.stylefeng.guns.modular.transport.service.TraceService;
import cn.stylefeng.guns.modular.transport.utils.MapTrackUtils;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

@Api(tags = "rest轨迹服务")
@Controller
@RequestMapping("/rest/track")
public class restTrackController {

    @Autowired
    private UserAop userAop;
    @Autowired
    private MapTrackUtils mapTrackUtils;
    @Autowired
    private TraceService traceService;
    @Autowired
    private BasicPrivatecarService basicPrivatecarService;
    @Autowired
    private MapDisptchService mapDisptchService;

    @Autowired
    private MongoTemplate mongoTemplate;
    // 查询终端
    @ApiOperation(value = "查询终端", notes = "根据服务id和终端id查询终端")
    @ResponseBody
    @RequestMapping(value = "/queryTerminals",method = {RequestMethod.GET})
    public ResponseData queryTerminals(@RequestParam String sid,
                                       @RequestParam(required = false) String tid,
                                       @RequestParam(required = false) String name,
                                       @RequestParam(required = false) Integer page) {
        try {
            String result = mapTrackUtils.queryTerminals(sid, tid, name, page);
            return ResponseData.success(result);
        } catch (Exception e) {
            return ResponseData.error("查询终端失败：" + e.getMessage());
        }
    }

    // 创建终端
    @ApiOperation(value = "创建终端", notes = "根据服务id创建终端")
    @ResponseBody
    @RequestMapping(value = "/createTerminal",method = {RequestMethod.POST})
    public ResponseData createTerminal(@RequestParam String sid,
                                       @RequestParam String name,
                                       @RequestParam(required = false) String desc) {
        try {
            String result = mapTrackUtils.createTerminal(sid, name, desc);
            return ResponseData.success(result);
        } catch (Exception e) {
            return ResponseData.error("创建终端失败：" + e.getMessage());
        }
    }


    // 创建轨迹
    @ApiOperation(value = "创建轨迹", notes = "根据服务id和终端id创建轨迹")
    @ResponseBody
    @RequestMapping(value = "/createTrace",method = {RequestMethod.POST})
    public ResponseData createTrace(@RequestParam String sid,
                                    @RequestParam String tid,
                                    @RequestParam String trname) {
        try {
//            User user = userAop.getUser();
            String result = mapTrackUtils.createTrace(sid, tid, trname);
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(result);
            String trid = jsonNode.path("data").path("trid").asText();

            TraceParam traceParam = new TraceParam();
            traceParam.setServiceId(sid);
            traceParam.setTerminalId(tid);
            traceParam.setTraceId(trid);
            traceParam.setTraceName(trname);
//            traceParam.setUserId(user.getUserId());
//            traceService.add(traceParam);

            return ResponseData.success(result);
        } catch (Exception e) {
            return ResponseData.error("创建轨迹失败：" + e.getMessage());
        }
    }

    // 上传轨迹点
    @ApiOperation(value = "上传轨迹点", notes = "根据服务id和终端id和轨迹id上传轨迹点")
    @ResponseBody
    @RequestMapping(value = "/uploadTracePoint",method = {RequestMethod.POST})
    public ResponseData uploadTracePoint(@RequestBody MapServiceResult mapServiceResult) {
        try {
            String result = mapTrackUtils.uploadTracePoint(mapServiceResult.getSid(), mapServiceResult.getTid(), mapServiceResult.getTrid(), mapServiceResult.getPoints());
            return ResponseData.success(result);
        } catch (Exception e) {
            return ResponseData.error("上传轨迹点失败：" + e.getMessage());
        }
    }

//    // TODO 上传轨迹点 到本地
//    // 上传轨迹点 到本地
//    @ApiOperation(value = "上传轨迹点", notes = "根据服务id和终端id和轨迹id上传轨迹点到本地")
//    @ResponseBody
//    @RequestMapping(value = "/uploadTracePointLocal",method = {RequestMethod.POST})
//    public ResponseData uploadTracePointLocal(@RequestBody MapDisptchParam mapDisptch) {
////        try {
////            MapDisptch oldMapDisptch = mapDisptchService.getById(mapDisptch.getDispatchNumber());
////            MapDisptch entity = new MapDisptch();
////            ToolUtil.copyProperties(mapDisptch, entity);
////            String points = entity.getPoints();
////            JSONArray jsonpointsArray = new JSONArray(points);
////            Object locatetime = jsonpointsArray.stream().max(Comparator.comparingLong(o -> ((JSONObject) o).getLong("locatetime")))
////                    .orElse("");
////            String lastPoints = locatetime.toString();
////            entity.setPoints(points);
////            entity.setLastPoints(lastPoints);
////            if (oldMapDisptch == null){
////
////                mapDisptchService.insert(entity);
////            }else {
////                String oldpoints = oldMapDisptch.getPoints();
//////                String oldpointsJson = JSONUtils.toJSONString(oldpoints);
//////                JSONArray jsonArray = new JSONArray();
////                JSONArray jsonArray = new JSONArray(oldpoints);
////                JSONArray jsonArrayNew =new JSONArray(points);
////                jsonArrayNew.stream().forEach(o -> {
////                    JSONObject jsonObject = (JSONObject) o;
////                    jsonArray.put(jsonObject);
////                });
////
////                oldMapDisptch.setLastPoints(lastPoints);
////                oldMapDisptch.setPoints(jsonArray.toString());
////                mapDisptchService.updateMapDisptchById(oldMapDisptch);
////            }
//
//            return ResponseData.success("成功");
////        } catch (Exception e) {
////            return ResponseData.error("上传轨迹点失败：" + e.getMessage());
////        }
//    }

    @ApiOperation(value = "上传轨迹点", notes = "根据服务id和终端id和轨迹id上传轨迹点到本地")
    @ResponseBody
    @RequestMapping(value = "/uploadTracePointLocal",method = {RequestMethod.POST})
    @Async("taskExecutor")
    public ResponseData uploadTracePointLocal(@RequestBody MapDisptchMongo mapDisptch) {
        traceService.uploadTracePointLocal(mapDisptch);
        return ResponseData.success();
    }


    /**
     * 1、根据服务id 查询终端列表,和司机车牌号匹配
     * 2、如果存在取到终端id，如果不存在创建终端(name=司机车牌号)    ==返回 tid
     * 3、创建轨迹实体（trname=货运订单号）                       ==返回 trid
     * 4、返回 sid，tid，trid
     */
    @ApiOperation(value = "创建轨迹实体", notes = "盘点终端是否存在，创建轨迹")
    @ResponseBody
    @RequestMapping(value = "/checkTerminals",method = {RequestMethod.POST})
    public MapServiceResult checkTerminals(@RequestParam String carnumbger ,
                                          @RequestParam String dispatchNumber){
        try {
            // 蜀能key 1039108 蜀能测试sid2 1038650
            // like的keyOne 1038488
            String sid = "1039108";
            String tid;
            String trid;
            String terminalName;
            User user = userAop.getUser();

            // 1、根据服务id 查询终端列表,和司机车牌号匹配
            String terminals = mapTrackUtils.queryTerminals(sid,null , carnumbger, null);
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(terminals);
            String errcode = jsonNode.path("errcode").asText();
            if (!"10000".equals(errcode)){
                throw new RuntimeException("创建终端轨迹失败:"+ jsonNode.path("errmsg").asText());
            }
            String count = jsonNode.path("data").path("count").asText();
            // 2、存在终端直接创建轨迹
            if ("1".equals(count)){
                JsonNode results = jsonNode.path("data").path("results");
                JsonNode firstTerminal = results.get(0);
                tid = firstTerminal.path("tid").asText();
                terminalName = carnumbger;
            }else {
                // 3、创建终端
                String result = mapTrackUtils.createTerminal(sid, carnumbger, carnumbger);
                JsonNode jsonNode2 = objectMapper.readTree(result);
                tid = jsonNode2.path("data").path("tid").asText();
                terminalName = carnumbger;
            }
            // 4、查询轨迹，创建轨迹
            QueryWrapper<Trace> traceQueryWrapper = new QueryWrapper<>();
            traceQueryWrapper.eq("service_id",sid)
                            .eq("terminal_id",tid)
                            .eq("trace_name",carnumbger+"-"+dispatchNumber);
            Trace trace = traceService.getOne(traceQueryWrapper);

            if (trace != null && trace.getTraceId() != null && !trace.getTraceId().isEmpty()){
                trid = trace.getTraceId();
            }else {
                String result = mapTrackUtils.createTrace(sid, tid, carnumbger+"-"+dispatchNumber);
                JsonNode jsonNode3 = objectMapper.readTree(result);
                trid = jsonNode3.path("data").path("trid").asText();

                // 基础信息
                QueryWrapper<BasicPrivatecar> basicPrivatecarQueryWrapper = new QueryWrapper<>();
                basicPrivatecarQueryWrapper.eq("privatecar_number", carnumbger);
                BasicPrivatecar basicPrivatecar = basicPrivatecarService.getOne(basicPrivatecarQueryWrapper);

                TraceParam traceParam = new TraceParam();
                traceParam.setServiceId(sid);
                traceParam.setTerminalId(tid);
                traceParam.setTraceId(trid);
                traceParam.setTerminalName(terminalName);
                traceParam.setTraceName(carnumbger+"-"+dispatchNumber);
                traceParam.setUserId(user.getUserId());
                traceParam.setStartTime(String.valueOf(new Date().getTime()));
                traceParam.setCreatedAt(new Date());
                traceParam.setPrivatecarId(basicPrivatecar.getId());
                traceParam.setOperateId(basicPrivatecar.getOperateId());
                traceParam.setOperateName(basicPrivatecar.getOperateName());
                traceParam.setPrivatecarFleetId(basicPrivatecar.getPrivatecarFleetId());
                traceParam.setPrivatecarFleetName(basicPrivatecar.getPrivatecarFleetName());
                traceService.add(traceParam);
            }

            MapServiceResult mapServiceResult = new MapServiceResult();
            mapServiceResult.setSid(sid);
            mapServiceResult.setTid(tid);
            mapServiceResult.setTrid(trid);
            return mapServiceResult;
        } catch (IOException e) {
            throw new RuntimeException("创建终端轨迹失败:"+e);
        }
    }

    // 更新完成时间
    @ApiOperation(value = "更新完成时间", notes = "更新完成时间")
    @ResponseBody
    @RequestMapping(value = "/updateTrace",method = {RequestMethod.POST})
    public ResponseData updateTrace(@RequestBody TraceParam traceParam ) {
        try {
            String traceName = traceParam.getTraceName();
            traceService.lambdaUpdate()
                    .eq(Trace::getTraceName, traceName)
                    .set(Trace::getEndTime, new Date())
                    .update();
            return ResponseData.success();
        }catch (Exception e){
            return ResponseData.error("更新完成时间失败：" + e.getMessage());
        }
    }

    /**
     * 轨迹点示例：
     * [
     *     {
     *         "location": "116.383428,39.9076",
     *         "locatetime": 1725945000000,
     *         "speed": 30,
     *         "direction": 90,
     *         "height": 50,
     *         "accuracy": 15
     *     },
     * ]
     */



}
